"""Debug logging support."""

import sublime_plugin
import time


logs = {}


class WindowLog:

    """Collection of log messages tied to a window."""

    view = None

    def __init__(self):
        self.messages = []

    def clear(self):
        self.messages.clear()
        if self.view:
            self.view.run_command("select_all")
            self.view.run_command("right_delete")

    def add_message(self, msg, args):
        if self.messages:
            previous_time = self.messages[-1].time
        else:
            previous_time = None
        lm = LogMessage(msg, args, previous_time)
        self.messages.append(lm)
        self._display_message(lm)

    def _display_message(self, msg):
        if self.view:
            text = msg.render()
            self.view.run_command('append', {'characters': text,
                                             'scroll_to_end': True})

    def open_view(self, window):
        view = window.new_file()
        view.set_scratch(True)
        view.settings().set('rust_log_view', window.id())
        view.settings().set('word_wrap', True)
        view.set_name('Rust Enhanced Debug Log')
        self.view = view
        for m in self.messages:
            self._display_message(m)


class LogMessage:
    def __init__(self, msg, args, previous_time):
        self.msg = msg
        self.args = args
        self.previous_time = previous_time
        self.time = time.time()

    def render(self):
        if self.previous_time is None:
            last_time = '+0.000'
        else:
            last_time = '+%.3f' % (self.time - self.previous_time,)
        if self.args:
            rendered = self.msg % self.args
        else:
            rendered = self.msg
        return '%s %s\n' % (last_time, rendered.rstrip())


def critical(window, msg, *args):
    """Add a log message and display it to the console."""
    log(window, msg, *args)
    if args:
        print(msg % args)
    else:
        print(msg)


def log(window, msg, *args):
    """Add a log message."""
    global logs
    wlog = logs.setdefault(window.id(), WindowLog())
    wlog.add_message(msg, args)


def clear_log(window):
    """Clear log messages."""
    try:
        logs[window.id()].clear()
    except KeyError:
        pass


class RustOpenLog(sublime_plugin.WindowCommand):

    """Opens a view to display log messages generated by the Rust Enhanced
    plugin."""

    def run(self):
        wlog = logs.setdefault(self.window.id(), WindowLog())
        if wlog.view:
            self.window.focus_view(wlog.view)
        else:
            wlog.open_view(self.window)


class RustLogEvent(sublime_plugin.ViewEventListener):

    @classmethod
    def is_applicable(cls, settings):
        return settings.has('rust_log_view')

    def on_pre_close(self):
        try:
            wlog = logs[self.view.settings().get('rust_log_view')]
        except KeyError:
            return
        else:
            wlog.view = None
